#
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#

"""
嵌套函数发射器

将嵌套函数编译为C++，复用 Lambda 的 lambda_base 模板。
关键差异：
- Lambda: 单表达式体
- 嵌套函数: 多语句体

本发射器通过静态方法 generate_struct_if_needed 被 StatementEmitter 调用，
不参与主发射器调度系统。
"""

from mcpy.ir import IRFunctionNode
from ..core.emitter import NodeTypeEmitter, EmitResult
from ..core.context import CodeGenContext
from .nested_function.struct_generator import (
    AsyncFunctionStructGenerator,
    FunctionStructGenerator,
    add_function_struct_to_context,
)
from .nested_function.utils import get_functor_name


class NestedFunctionEmitter(NodeTypeEmitter):
    """嵌套函数发射器（复用 Lambda 的 lambda_base 模板）"""

    def __init__(self):
        # 不参与主发射器调度，所以不注册任何节点类型
        super().__init__([])

    def can_emit(self, node, context: CodeGenContext) -> bool:
        """本发射器不参与主调度"""
        return False

    def emit(self, node, context: CodeGenContext) -> EmitResult:
        """本发射器不参与主调度"""
        return EmitResult(code="", precedence=0)

    @staticmethod  # type: ignore
    def generate_struct_if_needed(
        node: IRFunctionNode, context: CodeGenContext
    ) -> None:
        """为嵌套函数生成定义（由 StatementEmitter 调用）

        async函数生成为普通C++函数，非async函数生成为struct

        Args:
            node: 嵌套函数节点
            context: 代码生成上下文
        """
        # async函数和非async函数都生成struct（使用lambda_base）
        # 原因：Python语义支持async函数存储在容器、作为返回值等
        # 必须使用可存储在mc::variant中的类型
        struct_name = get_functor_name(node)
        ir_module = node.get_ir_module()
        if not ir_module:
            return

        # 检查是否已生成（避免重复）
        generated_structs = (
            ir_module.get_extension_param("_generated_nested_structs") or set()
        )
        if struct_name in generated_structs:
            return

        has_await = node.get_extension_param("has_await_expressions", False)
        if node.is_async and has_await:
            async_gen = AsyncFunctionStructGenerator()
            struct_code = async_gen.generate(node, context)
        else:
            function_gen = FunctionStructGenerator()
            struct_code = function_gen.generate(node, context)

        # 嵌套函数的结构体追加到列表后面，但会在模板中按定义顺序提取
        # 注意：不使用 prepend=True，因为那样会导致顺序反转
        add_function_struct_to_context(ir_module, struct_code, struct_name, prepend=False)

        generated_structs.add(struct_name)
        ir_module.set_extension_param(
            "_generated_nested_structs", generated_structs, replace_existing=True
        )
